package com.zhou.starter.jpacomment.config;

import cn.hutool.core.util.StrUtil;
import com.zhou.starter.jpacomment.enums.DbTypeEnum;
import com.zhou.starter.jpacomment.properties.JpaCommentProperties;
import com.zhou.starter.jpacomment.service.AlterCommentService;
import com.zhou.starter.jpacomment.service.JpaCommentService;
import com.zhou.starter.jpacomment.service.impl.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.sql.DataSource;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Map;

/**
 * @author lcz
 * @desc JpaCommentAutoConfig 配置
 * @mail lcz_0130@163.com
 * @date 2024/03/01
 */

@Configuration
@EnableConfigurationProperties({JpaCommentProperties.class})
@AutoConfigureAfter({EntityManager.class, JdbcTemplate.class, JpaProperties.class})
@ConditionalOnProperty(prefix = "jpa.comment", value = "enable", havingValue = "true")
public class JpaCommentAutoConfig {

    public static Logger logger = LoggerFactory.getLogger(JpaCommentAutoConfig.class);

    @PersistenceContext
    private EntityManager entityManager;

    @Resource
    private JdbcTemplate jdbcTemplate;

    @Resource
    DataSource dataSource;

    @Resource
    JpaProperties jpaProperties;

    /**
     * 数据库视图配置+数据库选择
     *
     * @return {@link AlterCommentService}
     */
    @Bean
    @ConditionalOnMissingBean
    public AlterCommentService alterCommentService() {
        try {
            DatabaseMetaData metaData = dataSource.getConnection().getMetaData();
            String databaseType = metaData.getDatabaseProductName().toUpperCase();
            String schema = "";
            AlterCommentService service;
            if (databaseType.contains(DbTypeEnum.MYSQL.getValue())) {
                schema = jdbcTemplate.queryForObject("select database() from dual", String.class);
                service = new MysqlAlterCommentServiceImpl();
            } else if (databaseType.contains(DbTypeEnum.SQLSERVER.getValue())) {
                schema = "dbo";
                String jpaDefaultSchema = "default_schema";
                Map<String, String> params = jpaProperties.getProperties();
                if (params != null && StrUtil.isNotBlank(params.get(jpaDefaultSchema))) {
                    schema = params.get(jpaDefaultSchema);
                }
                service = new SqlServerAlterCommentServiceImpl();
            } else if (databaseType.contains(DbTypeEnum.POSTGRESQL.getValue())) {
                schema = jdbcTemplate.queryForObject(" SELECT CURRENT_SCHEMA ", String.class);
                service = new PgSqlAlterCommentServiceImpl();
            } else if (databaseType.contains(DbTypeEnum.KINGBASE.getValue())) {
                schema = jdbcTemplate.queryForObject(" SELECT CURRENT_SCHEMA ", String.class);
                service = new KingBaseAlterCommentServiceImpl();
            } else if (databaseType.contains(DbTypeEnum.ORACLE.getValue())) {
                schema = jdbcTemplate.queryForObject("select SYS_CONTEXT('USERENV','CURRENT_SCHEMA') CURRENT_SCHEMA from dual", String.class);
                service = new OracleAlterCommentServiceImpl();
            } else if (databaseType.contains(DbTypeEnum.DM.getValue())) {
                schema = jdbcTemplate.queryForObject("select SYS_CONTEXT('USERENV','CURRENT_SCHEMA') CURRENT_SCHEMA from dual", String.class);
                service = new DMAlterCommentServiceImpl();
            } else {
                service = null;
                logger.error("还没有适应数据库为： {}", databaseType);
            }

            if (service != null) {
                service.setSchema(schema);
                service.setJdbcTemplate(jdbcTemplate);
                logger.debug("当前数据库schema为 {}", service.getSchema());
            }
            return service;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * JPacomment服务
     *
     * @return {@link JpaCommentService}
     */
    @Bean(initMethod = "init")
    @ConditionalOnMissingBean
    public JpaCommentService jpacommentService() {
        JpaCommentService service = new JpaCommentService();
        service.setEntityManager(entityManager);
        service.setAlterCommentService(alterCommentService());
        return service;
    }


}
